{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "raising-savannah",
   "metadata": {},
   "outputs": [],
   "source": [
    "import itertools\n",
    "import os\n",
    "import os.path as osp\n",
    "import pickle\n",
    "import urllib\n",
    "from collections import namedtuple\n",
    "\n",
    "import numpy as np\n",
    "import scipy.sparse as sp\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.nn.init as init\n",
    "import torch.optim as optim\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline # 魔法函数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "musical-calvin",
   "metadata": {},
   "source": [
    "# 数据集准备"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "referenced-playlist",
   "metadata": {},
   "outputs": [],
   "source": [
    "Data = namedtuple('Data', ['x', 'y', 'adjacency',\n",
    "                           'train_mask', 'val_mask', 'test_mask'])\n",
    "\n",
    "def tensor_from_numpy(x, device):\n",
    "    return torch.from_numpy(x).to(device)\n",
    "\n",
    "class CoraData(object):\n",
    "    download_url = \"https://github.com/kimiyoung/planetoid/raw/master/data\"\n",
    "    filenames = [\"ind.cora.{}\".format(name) for name in\n",
    "                 ['x', 'tx', 'allx', 'y', 'ty', 'ally', 'graph', 'test.index']]\n",
    "\n",
    "    def __init__(self, data_root=\"../data/cora\", rebuild=False):\n",
    "        \"\"\"Cora数据，包括数据下载，处理，加载等功能\n",
    "        当数据的缓存文件存在时，将使用缓存文件，否则将下载、进行处理，并缓存到磁盘\n",
    "\n",
    "        处理之后的数据可以通过属性 .data 获得，它将返回一个数据对象，包括如下几部分：\n",
    "            * x: 节点的特征，维度为 2708 * 1433，类型为 np.ndarray\n",
    "            * y: 节点的标签，总共包括7个类别，类型为 np.ndarray\n",
    "            * adjacency: 邻接矩阵，维度为 2708 * 2708，类型为 scipy.sparse.coo.coo_matrix\n",
    "            * train_mask: 训练集掩码向量，维度为 2708，当节点属于训练集时，相应位置为True，否则False\n",
    "            * val_mask: 验证集掩码向量，维度为 2708，当节点属于验证集时，相应位置为True，否则False\n",
    "            * test_mask: 测试集掩码向量，维度为 2708，当节点属于测试集时，相应位置为True，否则False\n",
    "\n",
    "        Args:\n",
    "        -------\n",
    "            data_root: string, optional\n",
    "                存放数据的目录，原始数据路径: ../data/cora\n",
    "                缓存数据路径: {data_root}/ch5_cached.pkl\n",
    "            rebuild: boolean, optional\n",
    "                是否需要重新构建数据集，当设为True时，如果存在缓存数据也会重建数据\n",
    "\n",
    "        \"\"\"\n",
    "        self.data_root = data_root\n",
    "        save_file = osp.join(self.data_root, \"ch5_cached.pkl\")\n",
    "        if osp.exists(save_file) and not rebuild:\n",
    "            print(\"Using Cached file: {}\".format(save_file))\n",
    "            self._data = pickle.load(open(save_file, \"rb\"))\n",
    "        else:\n",
    "            self._data = self.process_data()\n",
    "            with open(save_file, \"wb\") as f:\n",
    "                pickle.dump(self.data, f)\n",
    "            print(\"Cached file: {}\".format(save_file))\n",
    "    \n",
    "    @property\n",
    "    def data(self):\n",
    "        \"\"\"返回Data数据对象，包括x, y, adjacency, train_mask, val_mask, test_mask\"\"\"\n",
    "        return self._data\n",
    "\n",
    "    def process_data(self):\n",
    "        \"\"\"\n",
    "        处理数据，得到节点特征和标签，邻接矩阵，训练集、验证集以及测试集\n",
    "        引用自：https://github.com/rusty1s/pytorch_geometric\n",
    "        \"\"\"\n",
    "        print(\"Process data ...\")\n",
    "        _, tx, allx, y, ty, ally, graph, test_index = [self.read_data(\n",
    "            osp.join(self.data_root, name)) for name in self.filenames]\n",
    "        train_index = np.arange(y.shape[0])\n",
    "        val_index = np.arange(y.shape[0], y.shape[0] + 500)\n",
    "        sorted_test_index = sorted(test_index)\n",
    "\n",
    "        x = np.concatenate((allx, tx), axis=0)\n",
    "        y = np.concatenate((ally, ty), axis=0).argmax(axis=1)\n",
    "\n",
    "        x[test_index] = x[sorted_test_index]\n",
    "        y[test_index] = y[sorted_test_index]\n",
    "        num_nodes = x.shape[0]\n",
    "\n",
    "        train_mask = np.zeros(num_nodes, dtype=np.bool)\n",
    "        val_mask = np.zeros(num_nodes, dtype=np.bool)\n",
    "        test_mask = np.zeros(num_nodes, dtype=np.bool)\n",
    "        train_mask[train_index] = True\n",
    "        val_mask[val_index] = True\n",
    "        test_mask[test_index] = True\n",
    "        adjacency = self.build_adjacency(graph)\n",
    "        print(\"Node's feature shape: \", x.shape)\n",
    "        print(\"Node's label shape: \", y.shape)\n",
    "        print(\"Adjacency's shape: \", adjacency.shape)\n",
    "        print(\"Number of training nodes: \", train_mask.sum())\n",
    "        print(\"Number of validation nodes: \", val_mask.sum())\n",
    "        print(\"Number of test nodes: \", test_mask.sum())\n",
    "\n",
    "        return Data(x=x, y=y, adjacency=adjacency,\n",
    "                    train_mask=train_mask, val_mask=val_mask, test_mask=test_mask)\n",
    "\n",
    "    @staticmethod\n",
    "    def build_adjacency(adj_dict):\n",
    "        \"\"\"根据邻接表创建邻接矩阵\"\"\"\n",
    "        edge_index = []\n",
    "        num_nodes = len(adj_dict)\n",
    "        for src, dst in adj_dict.items():\n",
    "            edge_index.extend([src, v] for v in dst)\n",
    "            edge_index.extend([v, src] for v in dst)\n",
    "        # 去除重复的边\n",
    "        edge_index = list(k for k, _ in itertools.groupby(sorted(edge_index)))\n",
    "        edge_index = np.asarray(edge_index)\n",
    "        adjacency = sp.coo_matrix((np.ones(len(edge_index)), \n",
    "                                   (edge_index[:, 0], edge_index[:, 1])),\n",
    "                    shape=(num_nodes, num_nodes), dtype=\"float32\")\n",
    "        return adjacency\n",
    "\n",
    "    @staticmethod\n",
    "    def read_data(path):\n",
    "        \"\"\"使用不同的方式读取原始数据以进一步处理\"\"\"\n",
    "        name = osp.basename(path)\n",
    "        if name == \"ind.cora.test.index\":\n",
    "            out = np.genfromtxt(path, dtype=\"int64\")\n",
    "            return out\n",
    "        else:\n",
    "            out = pickle.load(open(path, \"rb\"), encoding=\"latin1\")\n",
    "            out = out.toarray() if hasattr(out, \"toarray\") else out\n",
    "            return out\n",
    "\n",
    "    @staticmethod\n",
    "    def normalization(adjacency):\n",
    "        \"\"\"计算 L=D^-0.5 * (A+I) * D^-0.5\"\"\"\n",
    "        adjacency += sp.eye(adjacency.shape[0])    # 增加自连接\n",
    "        degree = np.array(adjacency.sum(1))\n",
    "        d_hat = sp.diags(np.power(degree, -0.5).flatten())\n",
    "        return d_hat.dot(adjacency).dot(d_hat).tocoo()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "governmental-graph",
   "metadata": {},
   "source": [
    "# 图卷积层的定义 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "previous-nomination",
   "metadata": {},
   "outputs": [],
   "source": [
    "class GraphConvolution(nn.Module):\n",
    "    def __init__(self, input_dim, output_dim, use_bias=True):\n",
    "        \"\"\"图卷积：L*X*\\theta\n",
    "\n",
    "        Args:\n",
    "        ----------\n",
    "            input_dim: int\n",
    "                节点输入特征的维度\n",
    "            output_dim: int\n",
    "                输出特征维度\n",
    "            use_bias : bool, optional\n",
    "                是否使用偏置\n",
    "        \"\"\"\n",
    "        super(GraphConvolution, self).__init__()\n",
    "        self.input_dim = input_dim\n",
    "        self.output_dim = output_dim\n",
    "        self.use_bias = use_bias\n",
    "        self.weight = nn.Parameter(torch.Tensor(input_dim, output_dim))\n",
    "        if self.use_bias:\n",
    "            self.bias = nn.Parameter(torch.Tensor(output_dim))\n",
    "        else:\n",
    "            self.register_parameter('bias', None)\n",
    "        self.reset_parameters()\n",
    "\n",
    "    def reset_parameters(self):\n",
    "        init.kaiming_uniform_(self.weight)\n",
    "        if self.use_bias:\n",
    "            init.zeros_(self.bias)\n",
    "\n",
    "    def forward(self, adjacency, input_feature):\n",
    "        \"\"\"邻接矩阵是稀疏矩阵，因此在计算时使用稀疏矩阵乘法\n",
    "        前向传播，网络进行参数计算\n",
    "        Args: \n",
    "        -------\n",
    "            adjacency: torch.sparse.FloatTensor\n",
    "                邻接矩阵\n",
    "            input_feature: torch.Tensor\n",
    "                输入特征\n",
    "        \"\"\"\n",
    "        support = torch.mm(input_feature, self.weight)\n",
    "        output = torch.sparse.mm(adjacency, support)\n",
    "        if self.use_bias:\n",
    "            output += self.bias\n",
    "        return output\n",
    "\n",
    "    def __repr__(self):\n",
    "        return self.__class__.__name__ + ' (' \\\n",
    "            + str(self.input_dim) + ' -> ' \\\n",
    "            + str(self.output_dim) + ')'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "hispanic-georgia",
   "metadata": {},
   "source": [
    "# 模型定义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "working-riverside",
   "metadata": {},
   "outputs": [],
   "source": [
    "class GcnNet(nn.Module):\n",
    "    \"\"\"\n",
    "    定义一个包含两层GraphConvolution的模型\n",
    "    \"\"\"\n",
    "    def __init__(self, input_dim=1433):\n",
    "        super(GcnNet, self).__init__()\n",
    "        self.gcn1 = GraphConvolution(input_dim, 16)\n",
    "        self.gcn2 = GraphConvolution(16, 7)\n",
    "    \n",
    "    def forward(self, adjacency, feature):\n",
    "        h = F.relu(self.gcn1(adjacency, feature))\n",
    "        logits = self.gcn2(adjacency, h)\n",
    "        return logits"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "global-agency",
   "metadata": {},
   "source": [
    "# 模型训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "suspected-round",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 超参数定义\n",
    "LEARNING_RATE = 0.1\n",
    "WEIGHT_DACAY = 5e-4\n",
    "EPOCHS = 200\n",
    "DEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "buried-turkish",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using Cached file: ../data/cora\\ch5_cached.pkl\n"
     ]
    }
   ],
   "source": [
    "# 加载数据，并转换为torch.Tensor\n",
    "dataset = CoraData().data\n",
    "node_feature = dataset.x / dataset.x.sum(1, keepdims=True)  # 归一化数据，使得每一行和为1\n",
    "tensor_x = tensor_from_numpy(node_feature, DEVICE)\n",
    "tensor_y = tensor_from_numpy(dataset.y, DEVICE)\n",
    "tensor_train_mask = tensor_from_numpy(dataset.train_mask, DEVICE)\n",
    "tensor_val_mask = tensor_from_numpy(dataset.val_mask, DEVICE)\n",
    "tensor_test_mask = tensor_from_numpy(dataset.test_mask, DEVICE)\n",
    "normalize_adjacency = CoraData.normalization(dataset.adjacency)   # 规范化邻接矩阵\n",
    "\n",
    "num_nodes, input_dim = node_feature.shape\n",
    "indices = torch.from_numpy(np.asarray([normalize_adjacency.row, \n",
    "                                       normalize_adjacency.col]).astype('int64')).long()\n",
    "values = torch.from_numpy(normalize_adjacency.data.astype(np.float32))\n",
    "tensor_adjacency = torch.sparse.FloatTensor(indices, values, \n",
    "                                            (num_nodes, num_nodes)).to(DEVICE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "available-jurisdiction",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 模型定义：Model, Loss, Optimizer\n",
    "model = GcnNet(input_dim).to(DEVICE)\n",
    "criterion = nn.CrossEntropyLoss().to(DEVICE)\n",
    "optimizer = optim.Adam(model.parameters(), \n",
    "                       lr=LEARNING_RATE, \n",
    "                       weight_decay=WEIGHT_DACAY)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "discrete-ecology",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 训练主体函数\n",
    "def train():\n",
    "    loss_history = []\n",
    "    val_acc_history = []\n",
    "    model.train()\n",
    "    train_y = tensor_y[tensor_train_mask]\n",
    "    for epoch in range(EPOCHS):\n",
    "        logits = model(tensor_adjacency, tensor_x)  # 前向传播\n",
    "        train_mask_logits = logits[tensor_train_mask]   # 只选择训练节点进行监督\n",
    "        loss = criterion(train_mask_logits, train_y)    # 计算损失值\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()     # 反向传播计算参数的梯度\n",
    "        optimizer.step()    # 使用优化方法进行梯度更新\n",
    "        train_acc, _, _ = test(tensor_train_mask)     # 计算当前模型训练集上的准确率\n",
    "        val_acc, _, _ = test(tensor_val_mask)     # 计算当前模型在验证集上的准确率\n",
    "        # 记录训练过程中损失值和准确率的变化，用于画图\n",
    "        loss_history.append(loss.item())\n",
    "        val_acc_history.append(val_acc.item())\n",
    "        print(\"Epoch {:03d}: Loss {:.4f}, TrainAcc {:.4}, ValAcc {:.4f}\".format(\n",
    "            epoch, loss.item(), train_acc.item(), val_acc.item()))\n",
    "    \n",
    "    return loss_history, val_acc_history"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "substantial-technique",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试函数\n",
    "def test(mask):\n",
    "    model.eval()\n",
    "    with torch.no_grad():\n",
    "        logits = model(tensor_adjacency, tensor_x)\n",
    "        test_mask_logits = logits[mask]\n",
    "        predict_y = test_mask_logits.max(1)[1]\n",
    "        accuarcy = torch.eq(predict_y, tensor_y[mask]).float().mean()\n",
    "    return accuarcy, test_mask_logits.cpu().numpy(), tensor_y[mask].cpu().numpy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "comfortable-insert",
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_loss_with_acc(loss_history, val_acc_history):\n",
    "    fig = plt.figure()\n",
    "    ax1 = fig.add_subplot(111)\n",
    "    ax1.plot(range(len(loss_history)), loss_history,\n",
    "             c=np.array([255, 71, 90]) / 255.)\n",
    "    plt.ylabel('Loss')\n",
    "    \n",
    "    ax2 = fig.add_subplot(111, sharex=ax1, frameon=False)\n",
    "    ax2.plot(range(len(val_acc_history)), val_acc_history,\n",
    "             c=np.array([79, 179, 255]) / 255.)\n",
    "    ax2.yaxis.tick_right()\n",
    "    ax2.yaxis.set_label_position(\"right\")\n",
    "    plt.ylabel('ValAcc')\n",
    "    \n",
    "    plt.xlabel('Epoch')\n",
    "    plt.title('Training Loss & Validation Accuracy')\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "imperial-checklist",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 000: Loss 1.9411, TrainAcc 0.2786, ValAcc 0.1420\n",
      "Epoch 001: Loss 1.8628, TrainAcc 0.5071, ValAcc 0.3080\n",
      "Epoch 002: Loss 1.7780, TrainAcc 0.7071, ValAcc 0.5340\n",
      "Epoch 003: Loss 1.6576, TrainAcc 0.8286, ValAcc 0.5900\n",
      "Epoch 004: Loss 1.5207, TrainAcc 0.8929, ValAcc 0.6260\n",
      "Epoch 005: Loss 1.3690, TrainAcc 0.9357, ValAcc 0.7120\n",
      "Epoch 006: Loss 1.2112, TrainAcc 0.9571, ValAcc 0.7360\n",
      "Epoch 007: Loss 1.0559, TrainAcc 0.9714, ValAcc 0.7500\n",
      "Epoch 008: Loss 0.9012, TrainAcc 0.9786, ValAcc 0.7440\n",
      "Epoch 009: Loss 0.7629, TrainAcc 0.9571, ValAcc 0.7640\n",
      "Epoch 010: Loss 0.6406, TrainAcc 0.9643, ValAcc 0.7680\n",
      "Epoch 011: Loss 0.5387, TrainAcc 0.9786, ValAcc 0.7820\n",
      "Epoch 012: Loss 0.4522, TrainAcc 0.9857, ValAcc 0.7720\n",
      "Epoch 013: Loss 0.3868, TrainAcc 0.9857, ValAcc 0.7740\n",
      "Epoch 014: Loss 0.3335, TrainAcc 0.9929, ValAcc 0.7820\n",
      "Epoch 015: Loss 0.2943, TrainAcc 0.9929, ValAcc 0.7820\n",
      "Epoch 016: Loss 0.2649, TrainAcc 0.9929, ValAcc 0.7800\n",
      "Epoch 017: Loss 0.2437, TrainAcc 0.9929, ValAcc 0.7720\n",
      "Epoch 018: Loss 0.2279, TrainAcc 1.0, ValAcc 0.7720\n",
      "Epoch 019: Loss 0.2181, TrainAcc 1.0, ValAcc 0.7760\n",
      "Epoch 020: Loss 0.2109, TrainAcc 1.0, ValAcc 0.7760\n",
      "Epoch 021: Loss 0.2066, TrainAcc 1.0, ValAcc 0.7740\n",
      "Epoch 022: Loss 0.2033, TrainAcc 1.0, ValAcc 0.7720\n",
      "Epoch 023: Loss 0.2002, TrainAcc 1.0, ValAcc 0.7680\n",
      "Epoch 024: Loss 0.1966, TrainAcc 1.0, ValAcc 0.7680\n",
      "Epoch 025: Loss 0.1923, TrainAcc 1.0, ValAcc 0.7840\n",
      "Epoch 026: Loss 0.1870, TrainAcc 1.0, ValAcc 0.7800\n",
      "Epoch 027: Loss 0.1803, TrainAcc 1.0, ValAcc 0.7680\n",
      "Epoch 028: Loss 0.1740, TrainAcc 1.0, ValAcc 0.7780\n",
      "Epoch 029: Loss 0.1665, TrainAcc 1.0, ValAcc 0.7860\n",
      "Epoch 030: Loss 0.1601, TrainAcc 1.0, ValAcc 0.7740\n",
      "Epoch 031: Loss 0.1541, TrainAcc 1.0, ValAcc 0.7760\n",
      "Epoch 032: Loss 0.1488, TrainAcc 1.0, ValAcc 0.7780\n",
      "Epoch 033: Loss 0.1443, TrainAcc 1.0, ValAcc 0.7760\n",
      "Epoch 034: Loss 0.1411, TrainAcc 1.0, ValAcc 0.7740\n",
      "Epoch 035: Loss 0.1381, TrainAcc 1.0, ValAcc 0.7700\n",
      "Epoch 036: Loss 0.1361, TrainAcc 1.0, ValAcc 0.7760\n",
      "Epoch 037: Loss 0.1344, TrainAcc 1.0, ValAcc 0.7760\n",
      "Epoch 038: Loss 0.1331, TrainAcc 1.0, ValAcc 0.7720\n",
      "Epoch 039: Loss 0.1314, TrainAcc 1.0, ValAcc 0.7700\n",
      "Epoch 040: Loss 0.1301, TrainAcc 1.0, ValAcc 0.7740\n",
      "Epoch 041: Loss 0.1289, TrainAcc 1.0, ValAcc 0.7740\n",
      "Epoch 042: Loss 0.1275, TrainAcc 1.0, ValAcc 0.7720\n",
      "Epoch 043: Loss 0.1262, TrainAcc 1.0, ValAcc 0.7760\n",
      "Epoch 044: Loss 0.1249, TrainAcc 1.0, ValAcc 0.7760\n",
      "Epoch 045: Loss 0.1243, TrainAcc 1.0, ValAcc 0.7800\n",
      "Epoch 046: Loss 0.1245, TrainAcc 1.0, ValAcc 0.7780\n",
      "Epoch 047: Loss 0.1242, TrainAcc 1.0, ValAcc 0.7840\n",
      "Epoch 048: Loss 0.1224, TrainAcc 1.0, ValAcc 0.7820\n",
      "Epoch 049: Loss 0.1177, TrainAcc 1.0, ValAcc 0.7760\n",
      "Epoch 050: Loss 0.1169, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 051: Loss 0.1186, TrainAcc 1.0, ValAcc 0.7800\n",
      "Epoch 052: Loss 0.1172, TrainAcc 1.0, ValAcc 0.7820\n",
      "Epoch 053: Loss 0.1157, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 054: Loss 0.1172, TrainAcc 1.0, ValAcc 0.7800\n",
      "Epoch 055: Loss 0.1177, TrainAcc 1.0, ValAcc 0.7860\n",
      "Epoch 056: Loss 0.1163, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 057: Loss 0.1155, TrainAcc 1.0, ValAcc 0.7860\n",
      "Epoch 058: Loss 0.1164, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 059: Loss 0.1160, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 060: Loss 0.1143, TrainAcc 1.0, ValAcc 0.7820\n",
      "Epoch 061: Loss 0.1141, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 062: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7820\n",
      "Epoch 063: Loss 0.1139, TrainAcc 1.0, ValAcc 0.7860\n",
      "Epoch 064: Loss 0.1131, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 065: Loss 0.1137, TrainAcc 1.0, ValAcc 0.7840\n",
      "Epoch 066: Loss 0.1140, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 067: Loss 0.1136, TrainAcc 1.0, ValAcc 0.7820\n",
      "Epoch 068: Loss 0.1135, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 069: Loss 0.1145, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 070: Loss 0.1158, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 071: Loss 0.1170, TrainAcc 0.9929, ValAcc 0.7760\n",
      "Epoch 072: Loss 0.1185, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 073: Loss 0.1158, TrainAcc 1.0, ValAcc 0.7840\n",
      "Epoch 074: Loss 0.1109, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 075: Loss 0.1114, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 076: Loss 0.1144, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 077: Loss 0.1132, TrainAcc 1.0, ValAcc 0.7840\n",
      "Epoch 078: Loss 0.1123, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 079: Loss 0.1147, TrainAcc 1.0, ValAcc 0.7860\n",
      "Epoch 080: Loss 0.1155, TrainAcc 1.0, ValAcc 0.7840\n",
      "Epoch 081: Loss 0.1145, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 082: Loss 0.1145, TrainAcc 1.0, ValAcc 0.7840\n",
      "Epoch 083: Loss 0.1139, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 084: Loss 0.1140, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 085: Loss 0.1147, TrainAcc 1.0, ValAcc 0.7800\n",
      "Epoch 086: Loss 0.1132, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 087: Loss 0.1131, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 088: Loss 0.1146, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 089: Loss 0.1139, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 090: Loss 0.1134, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 091: Loss 0.1141, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 092: Loss 0.1142, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 093: Loss 0.1142, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 094: Loss 0.1143, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 095: Loss 0.1142, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 096: Loss 0.1140, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 097: Loss 0.1144, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 098: Loss 0.1145, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 099: Loss 0.1140, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 100: Loss 0.1141, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 101: Loss 0.1143, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 102: Loss 0.1142, TrainAcc 1.0, ValAcc 0.7860\n",
      "Epoch 103: Loss 0.1144, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 104: Loss 0.1145, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 105: Loss 0.1144, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 106: Loss 0.1143, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 107: Loss 0.1145, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 108: Loss 0.1146, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 109: Loss 0.1145, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 110: Loss 0.1146, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 111: Loss 0.1146, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 112: Loss 0.1145, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 113: Loss 0.1145, TrainAcc 1.0, ValAcc 0.7860\n",
      "Epoch 114: Loss 0.1146, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 115: Loss 0.1146, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 116: Loss 0.1146, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 117: Loss 0.1146, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 118: Loss 0.1147, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 119: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 120: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 121: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 122: Loss 0.1151, TrainAcc 1.0, ValAcc 0.8000\n",
      "Epoch 123: Loss 0.1152, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 124: Loss 0.1154, TrainAcc 1.0, ValAcc 0.8000\n",
      "Epoch 125: Loss 0.1159, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 126: Loss 0.1169, TrainAcc 1.0, ValAcc 0.8000\n",
      "Epoch 127: Loss 0.1179, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 128: Loss 0.1192, TrainAcc 1.0, ValAcc 0.8000\n",
      "Epoch 129: Loss 0.1181, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 130: Loss 0.1150, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 131: Loss 0.1115, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 132: Loss 0.1128, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 133: Loss 0.1166, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 134: Loss 0.1175, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 135: Loss 0.1160, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 136: Loss 0.1145, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 137: Loss 0.1155, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 138: Loss 0.1172, TrainAcc 1.0, ValAcc 0.8020\n",
      "Epoch 139: Loss 0.1168, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 140: Loss 0.1153, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 141: Loss 0.1142, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 142: Loss 0.1147, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 143: Loss 0.1158, TrainAcc 1.0, ValAcc 0.8000\n",
      "Epoch 144: Loss 0.1159, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 145: Loss 0.1152, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 146: Loss 0.1147, TrainAcc 1.0, ValAcc 0.8000\n",
      "Epoch 147: Loss 0.1153, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 148: Loss 0.1160, TrainAcc 1.0, ValAcc 0.8020\n",
      "Epoch 149: Loss 0.1158, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 150: Loss 0.1152, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 151: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 152: Loss 0.1150, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 153: Loss 0.1155, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 154: Loss 0.1155, TrainAcc 1.0, ValAcc 0.7860\n",
      "Epoch 155: Loss 0.1152, TrainAcc 1.0, ValAcc 0.8000\n",
      "Epoch 156: Loss 0.1149, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 157: Loss 0.1149, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 158: Loss 0.1151, TrainAcc 1.0, ValAcc 0.8040\n",
      "Epoch 159: Loss 0.1154, TrainAcc 1.0, ValAcc 0.7860\n",
      "Epoch 160: Loss 0.1155, TrainAcc 1.0, ValAcc 0.8000\n",
      "Epoch 161: Loss 0.1152, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 162: Loss 0.1150, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 163: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 164: Loss 0.1149, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 165: Loss 0.1151, TrainAcc 1.0, ValAcc 0.8020\n",
      "Epoch 166: Loss 0.1152, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 167: Loss 0.1152, TrainAcc 1.0, ValAcc 0.8020\n",
      "Epoch 168: Loss 0.1150, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 169: Loss 0.1149, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 170: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 171: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 172: Loss 0.1149, TrainAcc 1.0, ValAcc 0.8000\n",
      "Epoch 173: Loss 0.1150, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 174: Loss 0.1151, TrainAcc 1.0, ValAcc 0.8020\n",
      "Epoch 175: Loss 0.1150, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 176: Loss 0.1150, TrainAcc 1.0, ValAcc 0.8020\n",
      "Epoch 177: Loss 0.1149, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 178: Loss 0.1149, TrainAcc 1.0, ValAcc 0.8020\n",
      "Epoch 179: Loss 0.1149, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 180: Loss 0.1149, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 181: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 182: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 183: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 184: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 185: Loss 0.1149, TrainAcc 1.0, ValAcc 0.7960\n",
      "Epoch 186: Loss 0.1149, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 187: Loss 0.1149, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 188: Loss 0.1149, TrainAcc 1.0, ValAcc 0.7980\n",
      "Epoch 189: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7940\n",
      "Epoch 190: Loss 0.1148, TrainAcc 1.0, ValAcc 0.8020\n",
      "Epoch 191: Loss 0.1148, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 192: Loss 0.1149, TrainAcc 1.0, ValAcc 0.8040\n",
      "Epoch 193: Loss 0.1150, TrainAcc 1.0, ValAcc 0.7900\n",
      "Epoch 194: Loss 0.1152, TrainAcc 1.0, ValAcc 0.8040\n",
      "Epoch 195: Loss 0.1155, TrainAcc 1.0, ValAcc 0.7880\n",
      "Epoch 196: Loss 0.1162, TrainAcc 1.0, ValAcc 0.8040\n",
      "Epoch 197: Loss 0.1171, TrainAcc 1.0, ValAcc 0.7920\n",
      "Epoch 198: Loss 0.1192, TrainAcc 1.0, ValAcc 0.8040\n",
      "Epoch 199: Loss 0.1212, TrainAcc 0.9929, ValAcc 0.7800\n",
      "Test accuarcy:  0.7910000085830688\n"
     ]
    }
   ],
   "source": [
    "loss, val_acc = train()\n",
    "test_acc, test_logits, test_label = test(tensor_test_mask)\n",
    "print(\"Test accuarcy: \", test_acc.item())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "exempt-planet",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_loss_with_acc(loss, val_acc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "horizontal-promotion",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x270fb3198b0>"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制测试数据的TSNE降维图\n",
    "from sklearn.manifold import TSNE\n",
    "tsne = TSNE()\n",
    "out = tsne.fit_transform(test_logits)\n",
    "fig = plt.figure()\n",
    "for i in range(7):\n",
    "    indices = test_label == i\n",
    "    x, y = out[indices].T\n",
    "    plt.scatter(x, y, label=str(i))\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "sitting-swift",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
